package com.kinyx.framework.tree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.util.XArrayList;

import com.kinyx.framework.Configs;
import com.kinyx.framework.annotation.assist.CanNotNull;
import com.kinyx.framework.annotation.assist.CanNull;
import com.kinyx.framework.annotation.assist.ReturnNotNull;
import com.kinyx.framework.annotation.assist.ReturnNull;
import com.kinyx.framework.annotation.assist.Tester;
import com.kinyx.framework.utils.KStringUtils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * 编码工具类
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Tester("com.kinyx.framework.tree.KCodeUtils_Tester_")
public final class KCodeUtils {

	/** 编码长度 */
	private static int LENGHT = 7;
	/** 层级编码 */
	private static final String[] strs = new String[]{
			"A", "B", "C", "D", "E", "F", "G", "H"
	};

	/**
	 * 补全编码
	 * @param code 编码
	 * @return 编码
	 */
	@ReturnNotNull
	public static String fill(@CanNull(defaultValue = Configs.ROOT) final String code) {
		if (KStringUtils.isBlank(code)) { return fill(Configs.ROOT); }
		if (code.equalsIgnoreCase(Configs.ROOT)) { return Configs.ROOT; }
		final int len = code.length() / (LENGHT + 1);
		final StringBuilder sb = new StringBuilder(code);
		for (int i = len; i < strs.length; i++) {
			sb.append(strs[i]).append(KStringUtils.fillZero(0, LENGHT));
		}
		return sb.toString();
	}

	/**
	 * 当前级别
	 * @param code 编码
	 * @return 级别
	 */
	@ReturnNotNull
	public static int level(@CanNull(defaultValue = Configs.ROOT) final String code) {
		if (KStringUtils.isBlank(code)) { return level(Configs.ROOT); }
		if (code.equalsIgnoreCase(Configs.ROOT)) { return 0; }
		for (int i = strs.length - 1; i >= 0; i--) {
			final int x = Integer.parseInt(code.substring((i * (LENGHT + 1)) + 1, (i + 1) * (LENGHT + 1)));
			if (x != 0) { return i + 1; }
		}
		return 1;
	}

	/**
	 * 真实编码
	 * @param code 编码
	 * @return 编码
	 */
	@ReturnNull("非编码")
	public static String real(@CanNull(defaultValue = Configs.ROOT) final String code) {
		if (KStringUtils.isBlank(code)) { return real(Configs.ROOT); }
		if (code.equalsIgnoreCase(Configs.ROOT)) { return ""; }
		for (int i = strs.length - 1; i >= 0; i--) {
			final int x = Integer.parseInt(code.substring((i * (LENGHT + 1)) + 1, (i + 1) * (LENGHT + 1)));
			if (x != 0) { return code.substring(0, ((i + 1) * (LENGHT + 1))); }
		}
		return null;
	}

	/**
	 * 下一个编码
	 * @param code 编码
	 * @return 编码
	 */
	@ReturnNotNull
	public static String next(@CanNotNull final String code) {
		int current = 0;
		int level = 0;
		for (int i = strs.length - 1; i >= 0; i--) {
			final int x = Integer.parseInt(code.substring((i * (LENGHT + 1)) + 1, (i + 1) * (LENGHT + 1)));
			if (x != 0) {
				current = x + 1;
				level = i;
				break;
			}
		}
		return fill(code.substring(0, (level * (LENGHT + 1)) + 1) + KStringUtils.fillZero(current, LENGHT));
	}

	/**
	 * 上一个编码
	 * @param code 编码
	 * @return 编码
	 */
	@ReturnNotNull
	public static String prev(@CanNotNull final String code) {
		int current = 0;
		int level = 0;
		for (int i = strs.length - 1; i >= 0; i--) {
			final int x = Integer.parseInt(code.substring((i * (LENGHT + 1)) + 1, (i + 1) * (LENGHT + 1)));
			if (x != 0) {
				current = x - 1;
				level = i;
				break;
			}
		}
		if (current == 0) { return null; }
		return fill(code.substring(0, (level * (LENGHT + 1)) + 1) + KStringUtils.fillZero(current, LENGHT));
	}

	/**
	 * 创建编码
	 * @param parentCode 上级编码
	 * @return 编码
	 */
	@ReturnNotNull
	public static String create(@CanNull(defaultValue = Configs.ROOT) final String parentCode) {
		final String realCode = real(parentCode);
		final int len = realCode.length() / (LENGHT + 1);
		final StringBuilder sb = new StringBuilder(realCode);
		sb.append(strs[len]).append(KStringUtils.fillZero(1, LENGHT));
		for (int i = len + 1; i < strs.length; i++) {
			sb.append(strs[i]).append(KStringUtils.fillZero(0, LENGHT));
		}
		return sb.toString();
	}

	/**
	 * 创建编码
	 * @param parentCode 上级编码
	 * @param orderId 排序号
	 * @return 编码
	 */
	@ReturnNotNull
	public static String create(@CanNull(defaultValue = Configs.ROOT) final String parentCode, @CanNotNull final int orderId) {
		String code = create(parentCode);
		for (int i = 1; i <= orderId; i++) {
			code = next(code);
		}
		return code;
	}

	/**
	 * 获取当前编码的所有上级编码
	 * @param code 编码
	 * @param withRoot true：包含ROOT编码；false：不包含ROOT编码；
	 * @return 所有上级编码
	 */
	@ReturnNotNull
	public static List<String> parentsCodes(@CanNull(defaultValue = Configs.ROOT) final String code, @CanNotNull final boolean withRoot) {
		if (KStringUtils.isBlank(code)) { return parentsCodes(Configs.ROOT, withRoot); }
		if (code.equalsIgnoreCase(Configs.ROOT)) { return withRoot ? new XArrayList<String>().xAdd(Configs.ROOT) : Collections.emptyList(); }
		final int level = level(code);
		final String realCode = real(code);
		final List<String> list = new ArrayList<>();
		for (int i = 1; i < level; i++) {
			final String parentCode = realCode.substring(0, realCode.length() - (i * (LENGHT + 1)));
			list.add(fill(parentCode));
		}
		if (withRoot) {
			list.add(Configs.ROOT);
		}
		return list;
	}

	/**
	 * 获取当前编码的所有上级编码
	 * @param codes 编码列表
	 * @param withRoot true：包含ROOT编码；false：不包含ROOT编码；
	 * @return 所有上级编码
	 */
	@ReturnNotNull
	public static List<String> parentsCodes(@CanNull final List<String> codes, final boolean withRoot) {
		if ((codes == null) || codes.isEmpty()) { return Collections.emptyList(); }
		final Set<String> set = new TreeSet<>((o1, o2) -> -o1.compareTo(o2));
		for (final String code : codes) {
			set.addAll(parentsCodes(code, false));
		}
		final List<String> list = new ArrayList<>(set);
		if (withRoot) {
			list.add(Configs.ROOT);
		}
		return list;
	}

}
